using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Serialization;

[System.Serializable]
public class Pair
{
    [Header("触发设置")]
    public SkillEventName TriggerEvents;
    public List<ConditionBase> Conditions; //条件
    public TargetSelectorBase TargetSelector;
    [Header("效果执行")]
    public List<EffectBase> Effects;
    
    [HideInInspector]
    public Chess Chess;

    public Pair()
    {
        
    }
    public Pair(SkillEventName triggerEvents,List<ConditionBase>  conditions,TargetSelectorBase targetSelector,List<EffectBase> effects,Chess chess)
    {
        TriggerEvents = triggerEvents;
        Conditions = conditions;
        TargetSelector = targetSelector;
        Effects = effects;
        Chess = chess;
    }
}


[CreateAssetMenu(fileName = nameof(SkillConfig), menuName = "Skill/SkillConfig")]
public class SkillConfig : ScriptableObject
{
    public List<Pair> conditionAndEffect = new List<Pair>();
    private Dictionary<Chess, List<Pair>> chessAndPair = new();
    private Dictionary<SkillEventName,int> eventCount = new();
    public void Init(Chess chess)
    {
        List<Pair> list = conditionAndEffect.Select(pair => new Pair(pair.TriggerEvents,pair.Conditions, pair.TargetSelector, pair.Effects, chess)).ToList();
        foreach (var pair in list)
        {
            if (eventCount.TryAdd(pair.TriggerEvents, 1))
            {
                EventCenter.GetInstance().AddEventListener<GameEvent>(pair.TriggerEvents.ToString(),OnEventReceived);
                Debug.LogWarning(pair.TriggerEvents.ToString());
            }
            else
            {
                eventCount[pair.TriggerEvents]++;
            }
        }

        chessAndPair.TryAdd(chess,list);

        
        if (chessAndPair.Count == 1)
        {
            EventCenter.GetInstance().AddEventListener<Chess>(GetInstanceID().ToString()+nameof(Remove),Remove);
        }
        removeList.Clear();
        
    }
    
    List<Chess> removeList = new List<Chess>();

    public void Remove(Chess chess)
    {
        removeList.Add(chess);
    }

    public void RemovePair()
    {
        lock (removeList)
        {
            foreach (var chess in removeList)
            {
                Debug.Log(chess.chessDate.chessName);
                chessAndPair.Remove(chess, out var list);
                if(list != null)
                    foreach (var pair in list)
                    {
                        eventCount[pair.TriggerEvents]--;
                        if (eventCount[pair.TriggerEvents] == 0)
                        {
                            eventCount.Remove(pair.TriggerEvents);
                            EventCenter.GetInstance()
                                .RemoveEventListener<GameEvent>(pair.TriggerEvents.ToString(), OnEventReceived);
                        }

                        foreach (var effect in pair.Effects)
                        {
                            effect.RemoveDictionary(pair);
                        }

                        foreach (var condition in pair.Conditions)
                        {
                            condition.RemoveDictionary(pair);
                        }

                    }
            }

            removeList.Clear();
        }
        
        if (chessAndPair.Count == 0)
        {
            eventCount.Clear();
            EventCenter.GetInstance().RemoveEventListener<Chess>(GetInstanceID().ToString()+nameof(Remove),Remove);
        }
    }
    

    private void OnEventReceived(GameEvent e)
    {
        RemovePair();
        foreach (Chess chess in chessAndPair.Keys.ToList())
        {
            foreach (Pair pair in chessAndPair[chess])
            {
                if (CheckConditions(pair, e))
                {
                    ExecuteEffects(pair, e);
                }
            }
        }

        RemovePair();
    }

    private bool CheckConditions(Pair pair,GameEvent e)
    {
        foreach (var condition in pair.Conditions)
        {
            if (!condition.Evaluate(pair, e)) return false;
        }

        return true;
    }

    private void ExecuteEffects(Pair pair,GameEvent e)
    {
        var targets = pair.TargetSelector.SelectTargets(pair.Chess,e);
        foreach (var effect in pair.Effects)
        {
            effect.Apply(pair,e, targets);
        }
    }
}
